home *** CD-ROM | disk | FTP | other *** search
- ; Copyright 1992 Eric R. Smith
- ; Copyright 1992,1993 Atari Corporation
- ; All rights reserved.
-
- %include "magic.i"
- ;
- ; syscall: interface for system calls. The following entry points are
- ; defined:
- ; _mint_bios: entry point for the BIOS calls (trap #13)
- ; _mint_xbios: entry point for XBIOS calls (trap #14)
- ; _mint_dos: entry point for GEMDOS calls (trap #1)
- ; _sig_return: user signal handlers return to this routine (see signal.c)
- ; it is responsible for restoring the kernel's old context
- ; via the Psigreturn() system call
- ; _lineA0: calls the line A initialize routine
- ; _call_aes: calls the GEM AES
- ; _call_dosound: calls the XBIOS Dosound() function
- ; _do_usrcall: calls a user supplied function (e.g. for Supexec), with
- ; arguments supplied from global variables usrarg1, usrarg2, etc.
- ; _callout: calls an external function, after first saving all registers,
- ; and restores the registers afterward
- ;
- ; external variables referenced:
- ; _bios_tab, _bios_max:
- ; table of entry points for BIOS routines, max # of routine
- ; _xbios_tab, _xbios_max:
- ; ditto for XBIOS
- ; _dos_tab, _dos_max:
- ; ditto for GEMDOS
- ; _curproc:
- ; pointer to current process table entry, and hence to save area for
- ; context (this is always the first entry in the PROC table).
- ; _valid_return:
- ; used to indicate to the kernel that a valid return from user mode
- ; is taking place
- ;
- ; _bconbuf, _bconbsiz, _bconbdev:
- ; 256 byte buffer for Bconout() output. If _bconbsiz is non-zero,
- ; there are that many bytes in _bconbuf waiting to be flushed. The
- ; output is for device _bconbdev.
- ;
- ; The C function enter_kernel() is called on entry to the kernel, and the
- ; function leave_kernel() is called on exit. These functions are responsible
- ; for saving and restoring the various trap vectors, so that MiNT can trap
- ; out to TOS directly, but programs can only trap to MiNT.
- ;
- ; we also call certain BIOS functions directly if these are known not to
- ; require saving/restoring of context
- ;
- TEXT
-
- XDEF _mint_bios,_mint_xbios
- XDEF _mint_dos
- XREF _build_context
- XREF _restore_context
- XREF _proc_clock ; controls process' allocation of CPU time
- XREF _enter_kernel
- XREF _leave_kernel
- XREF _preempt
-
- XREF _curproc
- XREF _bios_tab,_bios_max
- XREF _xbios_tab,_xbios_max,_old_xbios
- XREF _dos_tab,_dos_max
-
- XREF _bconbuf,_bconbsiz,_bconbdev
- XREF _bflush
-
- XREF _ubconstat,_do_bconin,_ubcostat,_kbshift
-
- _mint_dos:
- clr.w -(sp) ; no frame format needed
- ; NOTE: FOR NOW, WE PRESERVE A0 ACROSS GEMDOS CALLS. THIS WILL CHANGE
- ; SOMEDAY, DON'T RELY ON IT!!!
- move.l _curproc,d0 ; note: preserve all regs but d0
- addq.l #4,d0 ; for compatibility
-
- move.l d0,-(sp) ; push pointer to syscall context save
- jsr _build_context
- lea _dos_tab,a5 ; set syscall_tab
- move.w _dos_max,d5 ; set syscall_max
- ;
- ; copy parameters onto process stack. a0 and a1 were set by _build_context
- ;
-
- move.l _curproc,a0
- move.l (a0),sp ; this puts us in our private stack
- move.l 24(a1),-(sp) ; a1 was set by build_context
- move.l 20(a1),-(sp)
- move.l 16(a1),-(sp)
- move.l 12(a1),-(sp)
- move.l 8(a1),-(sp)
- move.l 4(a1),-(sp)
- move.l (a1),-(sp)
- move.w #1,-(sp) ; flag for in GEMDOS
- jsr _enter_kernel ; set up vectors appropriately
- addq.w #2,sp
- bra _syscall
-
- _mint_xbios:
- ;
- ; Kludge for Setscreen: under Falcon TOS, this
- ; calls a GEMDOS function (Srealloc) and so
- ; we must *not* change any of the vectors!!
-
- btst #5,(sp) ; test for user/super mode
- beq.s LX_usr
- %ifdef ONLY030
- lea 8(sp),a1
- %else
- lea 6(sp),a1 ; supervisor mode: args on stack
- tst.w ($59e).w ; test longframe
- beq.s LX_check
- addq.w #2,a1 ; stack is a bit bigger
- %endif
- bra.s LX_check
- LX_usr:
- move.l usp,a1 ; user mode: args on user stack
- LX_check:
- cmp.w #5,(a1) ; check for Setscreen command
- beq.s LX_screen ; no -- fall through
-
- clr.w -(sp) ; no frame format needed
- move.l _curproc,a0
- pea 4(a0) ; push pointer to syscall context save
- jsr _build_context
- lea _xbios_tab,a5 ; set syscall_tab
- move.w _xbios_max,d5 ; set syscall_max
- ;
- ; copy parameters onto process stack. a0 and a1 were set by _build_context
- ;
-
- move.l _curproc,a0
- move.l (a0),sp ; this puts us in our private stack
- move.l 24(a1),-(sp) ; a1 was set by build_context
- move.l 20(a1),-(sp)
- move.l 16(a1),-(sp)
- move.l 12(a1),-(sp)
- move.l 8(a1),-(sp)
- move.l 4(a1),-(sp)
- move.l (a1),-(sp)
- move.w #0,-(sp) ; flag: NOT GEMDOS
- jsr _enter_kernel ; set up vectors appropriately
- addq.w #2,sp
- bra _syscall
- ;
- ; For setscreen, jump directly to the ROM vector --
- ; this avoids all hazards (like changing the vectors)
-
- LX_screen:
- move.l _old_xbios+8,a0
- jmp (a0)
-
-
- _mint_bios:
- ;
- ; Entering the kernel can be very expensive; so, we take a short-cut
- ; if possible -- we try some BIOS functions out, and if they
- ; succeed without blocking then we're done; otherwise, we go
- ; through the long procedure for entering the kernel
- ;
- ; These shortcuts aren't done when we're called in supervisor mode,
- ; because TOS uses very tiny stacks (smaller than we want); the
- ; shortcuts operate on the user-supplied ssp, whereas the "full"
- ; BIOS code works on our (private) system stack
- ;
- ; the shortcuts are also turned off if BIOSBUF=n
- ;
- move.w #0,-(sp) ; flag: NOT a GEMDOS call
- jsr _enter_kernel ; set up BIOS vectors
- addq.w #2,sp
- tst.w _bconbdev ; is BIOS buffering on?
- bmi L_bios ; no; skip all this
-
- btst #5,(sp) ; test for user/super mode
- bne.s L_bios ; if super, goto L_bios
- tst.w _proc_clock ; are we about to be preempted?
- beq.s L_bios
-
- move.l usp,a1 ; user mode: args on user stack
- L_ubios:
- move.w (a1),d0 ; get command
- cmp.w #3,d0 ; Bconout?
- beq do_bconout ; yes -- go do it
- ;
- ; most of the remaining functions require BIOS vectors to be properly
- ; set up
- tst.w _bconbsiz ; is BIOS output waiting?
- bne.s L_bios ; yes -- do regular code
-
- ; test for various BIOS functions
- cmp.w #1,d0 ; Bconstat?
- bne.s L_00
- move.w 2(a1),-(sp) ; push arg
- jsr _ubconstat
- L_1out:
- addq.l #2,sp
- L_0out:
- move.l d0,-(sp) ; save d0
- ori.w #$0700,sr ; spl7()
- jsr _leave_kernel
- move.l (sp)+,d0 ; retrieve value to be returned
- rte ; return to user
- L_00:
- cmp.w #2,d0 ; Bconin?
- bne.s L_01
- move.w 2(a1),-(sp) ; yes; push argument
- jsr _do_bconin
- addq.w #2,sp
- cmp.w #$dead,d0 ; would Bconin block?
- bne.s L_0out ; no -- we're done
- bra.s L_bios ; yes -- do the long stuff
- L_01:
- cmp.w #8,d0 ; Bcostat?
- bne.s L_02
- move.w 2(a1),-(sp) ; push device
- jsr _ubcostat ; get status
- bra.s L_1out
- L_02:
- cmp.w #11,d0 ; Kbshift?
- bne.s L_bios
- move.w 2(a1),-(sp) ; push arg
- jsr _kbshift
- bra.s L_1out
-
- L_bios:
- clr.w -(sp) ; no frame format needed
- move.l _curproc,a0
- pea 4(a0) ; push pointer to syscall context save
- jsr _build_context
- lea _bios_tab,a5 ; set syscall_tab
- move.w _bios_max,d5 ; set syscall_max
- ;
- ; copy parameters onto process stack. a0 and a1 were set by _build_context
- ;
-
- move.l _curproc,a0
- move.l (a0),sp ; this puts us in our private stack
- move.l 24(a1),-(sp) ; a1 was set by build_context
- move.l 20(a1),-(sp)
- move.l 16(a1),-(sp)
- move.l 12(a1),-(sp)
- move.l 8(a1),-(sp)
- move.l 4(a1),-(sp)
- move.l (a1),-(sp)
-
- _syscall:
- ;
- ; check here to see if we need to flush the Bconout() buffer
- ;
- tst.w _bconbsiz ; characters in buffer?
- beq.s L_noflush ; no: OK to proceed
- ;
- ; watch out, this could cause a context switch
- ;
- jsr _bflush ; flush the buffer
-
- L_noflush:
- ;
- ; figure out which routine to call
- ;
- move.w (sp),d0
- cmp.w #-1,d0 ; trapping with -1 means return
- bne.s check_max ; the corresponding system table
- move.l a5,d0
- bra.s out
- check_max:
- cmp.w d5,d0
- bcc.s error
- add.w d0,d0
- add.w d0,d0 ; multiply by 4
- move.l 0(a5,d0.w),d0 ; d0 = syscall_tab[d0]
- beq.s error ; null entry means invalid call
- addq.w #2,sp ; pop function number off stack
- move.l d0,a0
- jsr (a0) ; go do the call
- out:
- move.l _curproc,a0
- move.l d0,P_SYSCTXT+C_D0(a0) ; set d0 in the saved context
- move.w P_SYSCTXT+C_SR(a0),d0 ; get saved status register
-
- tst.l P_PTRACER(a0) ; check curproc->ptracer, if not set
- beq.s notrace ; then no pending trace; this ensures
- move.w d0,d1 ; we work with non-MiNT debuggers
- and.w #$c000,d1 ; are either of the trace bits set
- sne P_SYSCTXT+C_PTRACE(a0) ; mark as trace pending/not
- notrace:
- tst.w _proc_clock ; has process exceeded time slice?
- bne.s nosleep ; no -- continue
- btst #13,d0 ; caller in supervisor mode?
- bne.s nosleep ; yes -- don't interrupt
- tst.w ($43e).w ; test floppy disk lock variable
- bne.s nosleep ; if locked, can't switch
- sleep:
- jsr _preempt ; does a sleep(READY_Q)
- nosleep:
- ori.w #$0700,sr ; spl7()
- jsr _leave_kernel ; restore vectors
- move.l _curproc,a0
- pea 4(a0)
- jsr _restore_context ; never returns
-
- ;
- ; we handle errors by calling through to GEMDOS or the BIOS/XBIOS,
- ; as appropriate, and letting them handle it -- that way, if the underlying
- ; system has functions we don't know about, they still work
- ; to figure out which trap we have to call, we use the system call
- ; table placed in a5 earlier
-
- error:
- cmp.l #_xbios_tab,a5
- bne.s maybe_bios
- trap #14
- bra.s out
- maybe_bios:
- cmp.l #_dos_tab,a5
- beq.s trap_1
- trap #13
- bra.s out
- trap_1:
- trap #1
- bra.s out
-
- ;
- ; sig_return: user signal handlers return to us. At that point, the
- ; stack looks like this:
- ; -4(sp) (long) sfmt
- ; (sp) (long) signal number -- was a parameter for user routine
- ;
- XDEF _sig_return
- XREF _valid_return
- _sig_return:
- addq.w #8,sp ; pop signal number and sfmt
- move.w #$11a,-(sp) ; Psigreturn() system call
- move.w #1,_valid_return ; tell kernel it's us!
- trap #1
- ; we had better not come back; if we did, something terrible
- ; happened, and we might as well terminate
- move.w #-998,-(sp)
- move.w #$4c,-(sp) ; Pterm()
- trap #1
- ;
- ; bconout special code: on entry, a1 points to the stack the user
- ; was using. If possible, we just buffer the output until later.
- ;
-
- do_bconout:
- tst.w _bconbdev ; is BIOS buffering on?
- bmi L_bios ; no buffering -- skip this code
- move.w 2(a1),d0 ; what device is this for?
- beq L_bios ; don't buffer the printer
- cmp.w _bconbdev,d0 ; same device as is buffered?
- bne.s new_dev ; no -- maybe we can't do this
- put_buf:
- move.w 4(a1),d0 ; get the character to output
- move.w _bconbsiz,d1 ; get index into buffer table
- cmp.w #255,d1 ; buffer full?
- beq L_bios ; yes -- flush it out
- lea _bconbuf,a0
- add.w d1,a0
- move.b d0,(a0) ; store the character
- addq.w #1,d1
- move.w d1,_bconbsiz
- jsr _leave_kernel ; restore vectors
- moveq.l #-1,d0 ; return character output OK
- rte
-
- new_dev:
- tst.w _bconbsiz ; characters already in buffer?
- bne L_bios ; yes: we can't buffer this one
- move.w d0,_bconbdev ; no: OK, we have a new device
- bra.s put_buf
-
- ;
- ; _lineA0: MiNT calls this to get the address of the line A variables
- ;
- XDEF _lineA0
- _lineA0:
- movem.l d2/a2,-(sp) ; save scratch registers
- dc.w $a000 ; call the line A initialization routine
- movem.l (sp)+,d2/a2
- rts
-
- ;
- ; _call_aes: calls the GEM AES, using the control block passed as
- ; a parameter. Used only for doing appl_init(), to see
- ; if the AES is active yet
- ;
- XDEF _call_aes
- _call_aes:
- move.l 4(sp),d1 ; fetch pointer to parameter block
- move.w #$c8,d0 ; magic number for AES
- movem.l d2/a2,-(sp) ; save scratch registers
- trap #2
- movem.l (sp)+,d2/a2
- rts
- ;
- ; _call_dosound:
- ;
- XDEF _call_dosound
- _call_dosound:
- move.l 4(sp),d0
- move.l d0,-(sp)
- move.w #32,-(sp)
- trap #14
- addq.w #6,sp
- rts
-
- ;
- ; _callout: Call an external function, passing <32 bytes of arguments,
- ; and return the value from the function. NOTE: we must be careful
- ; to save all registers here!
- ;
- XDEF _callout
- XDEF _callout1
- XDEF _callout2
- ;
- ; _callout is the general purpose one
- ;
- _callout:
- lea 8(sp),a0 ; pointer to args
- move.l 4(sp),a1 ; pointer to pointer to function
- movem.l d2-d7/a2-a6,-(sp) ; save registers
- movem.l (a0),d0-d7 ; copy parameters
- movem.l d0-d7,-(sp)
- suba.l a5,a5 ; the BIOS expects 0 in a5
- jsr (a1) ; go do it
- lea 32(sp),sp
- movem.l (sp)+,d2-d7/a2-a6 ; restore reggies
- rts
- ;
- ; _callout2 and _callout1 are for functions with just 1 or
- ; 2 16 bit parameters. We cheat and use the same code for
- ; both, since passing 32 bits isn't much more expensive than
- ; passing 16 bits (and since the called function will just
- ; ignore any extra arg)
- ;
-
- _callout1:
- _callout2:
- movem.l 4(sp),a0/a1 ; get function ptr & args
- movem.l d2-d7/a2-a6,-(sp) ; save reggies
- move.l a1,-(sp) ; push args
- suba.l a5,a5 ; the BIOS expects 0 in a5
- jsr (a0) ; do function
- addq.w #4,sp
- movem.l (sp)+,d2-d7/a2-a6 ; restore reggies
- rts
-
- ;
- ; do_usrcall: call the user supplied function (*usrcall)(), with
- ; arguments given in the longwords usrarg1..usrarg5. Return value
- ; is placed in usrret. This function is used by the Supexec code
- ; in xbios.c.
-
- XDEF _do_usrcall
- XREF _usrret
- XREF _usrcall
- XREF _usrarg1,_usrarg2,_usrarg3,_usrarg4,_usrarg5
-
- _do_usrcall:
- move.l _usrarg5,-(sp)
- move.l _usrarg4,-(sp)
- move.l _usrarg3,-(sp)
- move.l _usrarg2,-(sp)
- move.l _usrarg1,-(sp)
- move.l _usrcall,-(sp) ; the user expects to see this on the stack
- pea ucret(pc) ; so rts puts us back here
- move.l _usrcall,-(sp) ; this copy is for us to use
- rts ; to jump to (we don't want to use registers)
- ucret:
- lea 24(sp),sp ; fix up stack
- move.l d0,_usrret ; save returned value
- rts ; back to caller
-
- END
-